package com.yanqu.road.server.channelserver.manager.voucher;

import com.yanqu.road.entity.voucher.config.VoucherConfigInfo;
import com.yanqu.road.logic.bussiness.voucher.VoucherBusiness;
import com.yanqu.road.pb.voucher.VoucherProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.channelserver.logic.ChannelMessageHelper;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 代金券模块
 */
public class ChannelVoucherMgr extends TempMgr {

    // 来个大锁，拿兑换码都要加锁
    private static final Object lock = new Object();

    /**
     * 代金券列表   类型，代金券信息
     */
    private static Map<Integer, List<VoucherConfigInfo>> voucherMap = new ConcurrentHashMap<>();

    /**
     * 使用代金券
     */
    public static int voucherUse(int channelId, long serverId, long playerId, int type, String preCost, Map<Integer, List<BigInteger>> priceParamMap) {
        VoucherProto.ChannelVoucherUseRespMsg.Builder respMsg = VoucherProto.ChannelVoucherUseRespMsg.newBuilder();
        Property property = PropertyHelper.parseStringToProperty(preCost);
        if (property.isNothing()) {
            return GameErrorCode.E_ERROR_PARAMETER;
        }
        // 记录下实际扣除
        Property realCost = new Property();
        for (Map.Entry<Integer, BigInteger> entry : property.getGoods().entrySet()) {
            // 道具Id
            Integer goodsId = entry.getKey();
            // 道具数量
            int num = entry.getValue().intValue();
            if (num <= 0) {
                return GameErrorCode.E_ERROR_PARAMETER;
            }
            // 获取一下面值
            if (!priceParamMap.containsKey(goodsId)) {
                return GameErrorCode.E_ERROR_PARAMETER;
            }
            int price = priceParamMap.get(goodsId).get(0).intValue();
            for (int i = 0; i < num; i++) {
                VoucherConfigInfo voucherConfigInfo = randomVoucherConfigInfo(channelId, type, price, playerId);
                if (voucherConfigInfo == null) {
                    continue;
                }
                realCost.addProperty(new Property(goodsId, BigInteger.ONE));
                VoucherProto.UserVoucherDataTemp.Builder userVoucherDataTemp = VoucherProto.UserVoucherDataTemp.newBuilder();
                userVoucherDataTemp.setVoucherId(voucherConfigInfo.getVoucherId());
                userVoucherDataTemp.setPrice(voucherConfigInfo.getPrice());
                userVoucherDataTemp.setCode(voucherConfigInfo.getCode());
                userVoucherDataTemp.setType(voucherConfigInfo.getType());
                userVoucherDataTemp.setExpireTime(voucherConfigInfo.getEndTime());
                respMsg.addVoucherInfoTemp(userVoucherDataTemp);
            }
        }
        respMsg.setRet(0);
        respMsg.setPreCost(preCost);
        respMsg.setRealCost(PropertyHelper.parsePropertyToString(realCost));
        // 发送消息
        ChannelMessageHelper.sendGamePacket(Protocol.S_VOUCHER_USE_FROM_CROSS, respMsg, channelId, serverId, playerId);
        return 0;
    }

    /**
     * 随机抽取代金券
     */
    public static VoucherConfigInfo randomVoucherConfigInfo(int channelId, int type, int price, long userId) {
        long nowTime = System.currentTimeMillis();
        // 加个锁，防止并发
        synchronized (lock) {
            List<VoucherConfigInfo> voucherConfigInfoList = voucherMap.get(type);
            if (voucherConfigInfoList == null) {
                return null;
            }
            // 过滤掉已使用的代金券
            List<VoucherConfigInfo> tempVoucherConfigInfoList = new ArrayList<>();
            for (VoucherConfigInfo voucherConfigInfo : voucherConfigInfoList) {
                if (!voucherConfigInfo.getChannelId().contains(0) && !voucherConfigInfo.getChannelId().contains(channelId)) {
                    continue;
                }
                if (voucherConfigInfo.getUserId() > 0) {
                    continue;
                }
                // 判断一下面值
                if (voucherConfigInfo.getPrice() != price) {
                    continue;
                }
                // 判断下有效期
                if (voucherConfigInfo.getStartTime() > nowTime || voucherConfigInfo.getEndTime() < nowTime) {
                    continue;
                }
                tempVoucherConfigInfoList.add(voucherConfigInfo);
            }
            if (tempVoucherConfigInfoList.size() == 0) {
                return null;
            }
            // 随机抽取代金券
            int index = (int) (Math.random() * tempVoucherConfigInfoList.size());
            VoucherConfigInfo voucherConfigInfo = tempVoucherConfigInfoList.get(index);
            voucherConfigInfo.setUserId(userId);
            voucherConfigInfo.setUseTime(nowTime);
            return voucherConfigInfo;
        }
    }


    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        // 重新加载时,先检测下是否都入库了,防止出现脏数据
        for (List<VoucherConfigInfo> voucherConfigInfoList : voucherMap.values()) {
            for (VoucherConfigInfo voucherConfigInfo : voucherConfigInfoList) {
                if (voucherConfigInfo.isDirty()) {
                    // 还有未入库数据,先处理下
                    if (voucherConfigInfo.isInsertOption()) {
                        VoucherBusiness.addVoucherInfo(voucherConfigInfo);
                    } else if (voucherConfigInfo.isUpdateOption()) {
                        VoucherBusiness.updateVoucherInfo(voucherConfigInfo);
                    }
                }
            }
        }
        // 把代金券从数据库读出来
        voucherMap = VoucherBusiness.getVoucherConfigInfoMap();
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    @Override
    public boolean save() {
        for (List<VoucherConfigInfo> voucherConfigInfoList : voucherMap.values()) {
            for (VoucherConfigInfo voucherConfigInfo : voucherConfigInfoList) {
                if (voucherConfigInfo.isInsertOption()) {
                    VoucherBusiness.addVoucherInfo(voucherConfigInfo);
                } else if (voucherConfigInfo.isUpdateOption()) {
                    VoucherBusiness.updateVoucherInfo(voucherConfigInfo);
                }
            }
        }
        return true;
    }

    public Map<Integer, List<VoucherConfigInfo>> getVoucherMap() {
        return voucherMap;
    }

}
